using System;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using microsoft_TODO.DTOs;
using microsoft_TODO.Models;
using microsoft_TODO.MongoCore;
using MongoDB.Driver;

namespace microsoft_TODO.ServiceCore.Services
{
    public class UserService : IUserService
    {
        private IUserRepository _userRepository;
        private IListRepository _listRepository;
        private ITokenRepository _tokenRepository;
        private IMapper _mapper;

        public UserService(
            IUserRepository userRepository,
            IListRepository listRepository,
            ITokenRepository tokenRepository,
            IMapper mapper)
        {
            _userRepository = userRepository;
            _listRepository = listRepository;
            _tokenRepository = tokenRepository;
            _mapper = mapper;
        }

        public User Authenticate(string username, string password)
        {
            var entity = _userRepository.FirstOrDefault(u => u.Username == username.ToLower());
            if (entity == null)
                return null;

            var hasher = new PasswordHasher<User>();
            var result = hasher.VerifyHashedPassword(entity, entity.Password, password);
            if (result == PasswordVerificationResult.Failed)
                return null;

            return entity;
        }

        public bool CreateUser(RegisterDto dto)
        {
            var entity = _mapper.Map<User>(dto);
            var hasher = new PasswordHasher<User>();
            entity.Password = hasher.HashPassword(entity, entity.Password);
            var back = _userRepository.Insert(entity);
            if (string.IsNullOrEmpty(back.Id))
                return false;
            // 插入默认LIST - To-Do
            var listEntity = new CheckList<Task>
            {
                Title = "To-Do",
                Icon = "todo",
                ZIndex = 0,
                IsStatic = true,
                UserId = back.Id,
                Tasks = new System.Collections.Generic.List<Task>()
            };
            var backList = _listRepository.Insert(listEntity);
            return !string.IsNullOrEmpty(backList.Id);
        }

        public User GetUserById(string id)
        {
            return _userRepository.FirstOrDefault(u => u.Id == id);
        }

        public bool IsUsernameExistent(string username)
        {
            return _userRepository.IsExistent(u => u.Username.ToLower() == username);
        }

        public void UpsertRefreshToken(RefreshToken token)
        {
            var update = Builders<RefreshToken>.Update
                .Set(u => u.UserId, token.UserId)
                .Set(u => u.Token, token.Token)
                .Set(u => u.RefreshDate, token.RefreshDate);
            _tokenRepository.Upsert(u => u.UserId == token.UserId, update);
        }

        public bool IsExpiredRefreshToken(string userId, string token)
        {
            var entity = _tokenRepository.FirstOrDefault(u => u.UserId == userId && u.Token == token);
            return entity == null || entity.RefreshDate.AddDays(7) < DateTime.Now;
        }

        public void UpdateLogonTime(string id)
        {
            _userRepository.Update(
                u => u.Id == id,
                Builders<User>.Update.Set(v => v.LogonTime, DateTime.Now));
        }
    }
}
